home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 June / CHIP Haziran 2001.iso / prog / haziran / 19 / setup.exe / data.z / usb_diag_lib.pas < prev    next >
Pascal/Delphi Source File  |  2001-04-11  |  12KB  |  438 lines

  1. {
  2.  ----------------------------------------------------------------
  3.  File - USB_DIAG_LIB.PAS
  4.  
  5.  Utility functions for printing device information,
  6.  detecting USB devices
  7.  ----------------------------------------------------------------
  8. }
  9.  
  10. unit USB_diag_lib;
  11.  
  12. interface
  13.  
  14. uses
  15.     Windows,
  16.     SysUtils,
  17.     WinDrvr_USB,
  18.     WinDrvr,
  19.     print_struct;
  20.  
  21. type READ_PIPE_FUNC = function(hDevice : HANDLE; pBuffer : POINTER; dwSize : DWORD) : DWORD; stdcall;
  22. type PROCESS_DATA_FUNC = procedure(pBuffer : POINTER; dwSize : DWORD; pContext : POINTER) stdcall;
  23. type STOP_PIPE_FUNC = procedure(hDevice : HANDLE) stdcall;
  24.  
  25. const
  26.     MAX_BUFFER_SIZE = 4096;
  27.     BYTES_IN_LINE = 16;
  28.     HEX_CHARS_PER_BYTE = 3; {2 digits and one space}
  29.     HEX_STOP_POS = BYTES_IN_LINE*HEX_CHARS_PER_BYTE;
  30.  
  31. type
  32.     USB_LISTEN_PIPE = record
  33.         read_pipe_func : READ_PIPE_FUNC;
  34.         stop_pipe_func : STOP_PIPE_FUNC;
  35.     hDevice : HANDLE;
  36.     dwPacketSize : DWORD;
  37.         process_data_func : PROCESS_DATA_FUNC; { if NULL call PrintHexBuffer }
  38.     pContext : PVOID;
  39.     fStopped : BOOLEAN;
  40.     hThread : HANDLE;
  41.     end;
  42.  
  43.     PUSB_LISTEN_PIPE = ^USB_LISTEN_PIPE;
  44.  
  45. function USB_Get_WD_handle(phWD : PHANDLE) : BOOLEAN;
  46. procedure USB_Print_device_info(dwVendorId : DWORD; dwProductId : DWORD);
  47. procedure USB_Print_all_devices_info;
  48. procedure USB_Print_device_Configurations(uniqueId : DWORD; configIndex : DWORD);
  49.  
  50. procedure PrintHexBuffer(pBuffer : POINTER; dwBytes : DWORD);
  51. function GetHexBuffer(pBuffer : POINTER; dwBytes : DWORD) : DWORD;
  52. function GetHexChar (line : string) : INTEGER;
  53. procedure CloseListening(pListenPipe : PUSB_LISTEN_PIPE);
  54. procedure ListenToPipe(pListenPipe : PUSB_LISTEN_PIPE);
  55. function PipeListenHandler(pParam : POINTER) : DWORD stdcall;
  56. function IsHexDigit(c : string) : BOOLEAN;
  57.  
  58.  
  59. implementation
  60.  
  61. function  pipeType2Str(pipeType : DWORD) : STRING;
  62. begin
  63.     case pipeType of
  64.     UsbdPipeTypeControl:
  65.         pipeType2Str := 'Control';
  66.     UsbdPipeTypeIsochronous:
  67.         pipeType2Str := 'Isochronous';
  68.     UsbdPipeTypeBulk:
  69.         pipeType2Str := 'Bulk';
  70.     UsbdPipeTypeInterrupt:
  71.         pipeType2Str := 'Interrupt';
  72.     else
  73.         pipeType2Str := 'Unknown';
  74.     end;
  75. end;
  76.  
  77.  
  78. function USB_Get_WD_handle(phWD : PHANDLE) : BOOLEAN;
  79. var
  80.     ver : SWD_VERSION;
  81.  
  82. begin
  83.     phWD^ := INVALID_HANDLE_VALUE;
  84.     phWD^ := WD_Open();
  85.  
  86.     { Check whether handle is valid and version OK }
  87.     if phWD^ = INVALID_HANDLE_VALUE
  88.     then
  89.     begin
  90.         Writeln('Cannot open WinDriver device');
  91.         USB_Get_WD_handle := False;
  92.         Exit;
  93.     end;
  94.  
  95.     FillChar(ver, SizeOf(ver), 0);
  96.     WD_Version(phWD^,ver);
  97.     if ver.dwVer<WD_VER
  98.     then
  99.     begin
  100.         Writeln('Error - incorrect WinDriver version');
  101.         WD_Close (phWD^);
  102.         phWD^ := INVALID_HANDLE_VALUE;
  103.         USB_Get_WD_handle := False;
  104.     end
  105.     else
  106.         USB_Get_WD_handle := True;
  107. end;
  108.  
  109.  
  110. procedure USB_Print_device_info(dwVendorId : DWORD; dwProductId : DWORD);
  111. var
  112.     i : DWORD;
  113.     {strTransType, strStatus : STRING;}
  114.     hWD : HANDLE;
  115.     usbScan : WD_USB_SCAN_DEVICES;
  116.     {openCloseInfo : WD_USB_OPEN_CLOSE;}
  117.     genInfo : PWD_USB_DEVICE_GENERAL_INFO;
  118.     tmp : string;
  119.  
  120. begin
  121.     if not USB_Get_WD_handle (@hWD)
  122.     then
  123.         Exit;
  124.  
  125.     FillChar(usbScan, SizeOf(usbScan), 0);
  126.     usbScan.searchId.dwVendorId  := dwVendorId;
  127.     usbScan.searchId.dwProductId := dwProductId;
  128.     WD_UsbScanDevice(hWD,@usbScan);
  129.     for i:=1 to usbScan.dwDevices do
  130.     begin
  131.         genInfo := @usbScan.deviceGeneralInfo[i];
  132.  
  133.         Writeln('USB device - Vendor ID: ', IntToHex(usbScan.deviceGeneralInfo[i-1].deviceId.dwVendorId, 4),
  134.             ', Product ID: ', IntToHex(usbScan.deviceGeneralInfo[i-1].deviceId.dwProductId, 4),
  135.             ', unique ID: ', usbScan.uniqueId[i-1]);
  136.         Writeln('      phisical address: 0x', IntToHex(usbScan.deviceGeneralInfo[i-1].deviceAddress, 4),
  137.             ' Hub No. ',usbScan.deviceGeneralInfo[i-1].dwHubNum,
  138.             ' Port No.',usbScan.deviceGeneralInfo[i-1].dwPortNum);
  139.         if usbScan.deviceGeneralInfo[i-1].fFullSpeed <> 0 then
  140.             Writeln('      Full speed, device has ',usbScan.deviceGeneralInfo[i-1].dwConfigurationsNum,
  141.                 'configuration(s)')
  142.         else
  143.             Writeln('      Low speed, device has ',usbScan.deviceGeneralInfo[i-1].dwConfigurationsNum,
  144.                ' configuration(s)');
  145.  
  146.         if genInfo^.fHub <> 0 then
  147.            if genInfo^.hubInfo.fBusPowered = 1 then
  148.                Writeln('      Device is Hub, Hub has ', genInfo^.hubInfo.dwPorts,
  149.                 ' ports, Bus powered, ',genInfo^.hubInfo.dwHubControlCurrent,
  150.                 ' mA')
  151.            else
  152.                Writeln('      Device is Hub, Hub has ', genInfo^.hubInfo.dwPorts,
  153.                 ' ports, Self powered, ',genInfo^.hubInfo.dwHubControlCurrent,
  154.                 ' mA');
  155.         Writeln('');
  156.         if i < usbScan.dwDevices then
  157.         begin
  158.            Writeln('Press Enter to continue to the next device');
  159.            Readln(tmp);
  160.         end;
  161.     end;
  162.     WD_Close (hWD);
  163. end;
  164.  
  165.  
  166. procedure USB_Print_all_devices_info;
  167. begin
  168.     USB_Print_device_info(0, 0);
  169. end;
  170.  
  171.  
  172. procedure USB_Print_device_Configurations(uniqueId : DWORD; configIndex :  DWORD);
  173. var
  174.     config : WD_USB_CONFIGURATION;
  175.     i, j : INTEGER;
  176.     hWD : HANDLE;
  177.     pInterface : PWD_USB_INTERFACE_DESC;
  178.     pEndPoint : PWD_USB_ENDPOINT_DESC;
  179.     tmp : string;
  180.  
  181. begin
  182.     if not USB_Get_WD_handle (@hWD)
  183.     then
  184.         Exit;
  185.  
  186.     FillChar(config, SizeOf(config), 0);
  187.     config.uniqueId := uniqueId;
  188.     config.dwConfigurationIndex := configIndex;
  189.     WD_UsbGetConfiguration(hWD, @config);
  190.  
  191.     Writeln('Configuration No. ', config.configuration.dwValue,
  192.         ' has ', config.configuration.dwNumInterfaces,
  193.         ' interface(s)');
  194.     Writeln('configuration attributes: 0x', IntToHex(config.configuration.dwAttributes, 2),
  195.         ' max power: ', config.configuration.MaxPower*2, 'mA');
  196.     Writeln('');
  197.  
  198.     for i:=0 to config.dwInterfaceAlternatives-1 do
  199.     begin
  200.         pInterface := @config.UsbInterface[i].InterfaceDesc;
  201.         Writeln('interface No. ', pInterface^.dwNumber,
  202.             ', alternate setting: ', pInterface^.dwAlternateSetting,
  203.             ', index: ', pInterface^.dwIndex);
  204.         Writeln('end-points: ', pInterface^.dwNumEndpoints,
  205.             ', class: 0x', IntToHex(pInterface^.dwClass, 2),
  206.             ', sub-class: 0x', IntToHex(pInterface^.dwSubClass, 2),
  207.             ', protocol: 0x', IntToHex(pInterface^.dwProtocol, 2));
  208.  
  209.         for j:=0 to pInterface^.dwNumEndpoints-1 do
  210.         begin
  211.             pEndPoint := @config.UsbInterface[i].Endpoints[j];
  212.             Writeln('  end-point address: 0x',IntToHex(pEndPoint^.dwEndpointAddress, 2),
  213.                 ', attributes: 0x', IntToHex(pEndPoint^.dwAttributes, 2),
  214.                 ', max packet size: ', pEndPoint^.dwMaxPacketSize,
  215.                 ', Interval: ',pEndPoint^.dwInterval);
  216.         end;
  217.         Writeln('');
  218.         if i < config.dwInterfaceAlternatives-1 then
  219.         begin
  220.            Writeln('Press Enter to continue to the next configuration');
  221.            Readln(tmp);
  222.         end;
  223.  
  224.     end;
  225.     WD_Close (hWD);
  226. end;
  227.  
  228.  
  229. procedure PrintHexBuffer(pBuffer : POINTER; dwBytes : DWORD);
  230. var
  231.     pData  : PBYTE;
  232.     pHex : array [0..HEX_STOP_POS-1] of CHAR; {48}
  233.     pAscii : array [0..BYTES_IN_LINE-1] of CHAR; {16}
  234.     offset, line_offset, i : DWORD;
  235.     intVal : INTEGER;
  236.     byteVal : BYTE;
  237.     hexStr : string;
  238.  
  239. begin
  240.     if dwBytes = 0 then
  241.        Exit;
  242.  
  243.     pData := pBuffer;
  244.  
  245.     for offset:=0 to dwBytes-1 do
  246.     begin
  247.         line_offset := offset mod BYTES_IN_LINE;
  248.  
  249.         if (offset <> 0) and (line_offset = 0) then
  250.         begin
  251.             Write(pHex, '| ', pAscii);
  252.             Writeln(' ');
  253.         end;
  254.         byteVal := PBYTE(DWORD(pData) + offset)^;
  255.         hexStr :=  IntToHex(byteVal, 2);
  256.  
  257.         pHex[line_offset*HEX_CHARS_PER_BYTE] := hexStr[1];
  258.         pHex[line_offset*HEX_CHARS_PER_BYTE+1] := hexStr[2];
  259.         pHex[line_offset*HEX_CHARS_PER_BYTE+2] := ' ';
  260.         if byteVal >= $20 then
  261.             pAscii[line_offset] := CHAR(byteVal)
  262.         else
  263.             pAscii[line_offset] := '.';
  264.     end;
  265.  
  266.     { print the last line. fill with blanks if needed }
  267.     if (offset mod BYTES_IN_LINE) <> 0 then
  268.     begin
  269.         for i:=(offset mod BYTES_IN_LINE)*HEX_CHARS_PER_BYTE to BYTES_IN_LINE*HEX_CHARS_PER_BYTE-1 do
  270.             pHex[i] := ' ';
  271.         for i:=(offset mod BYTES_IN_LINE) to BYTES_IN_LINE-1 do
  272.             pAscii[i] := ' ';
  273.     end;
  274.     Write(pHex, '| ', pAscii);
  275.     Writeln(' ');
  276. end;
  277.  
  278.  
  279. procedure CloseListening(pListenPipe : PUSB_LISTEN_PIPE);
  280. var
  281.     transfer : WD_USB_TRANSFER;
  282.  
  283. begin
  284.     FillChar(transfer, SizeOf(transfer), 0);
  285.  
  286.     if pListenPipe^.hThread = 0 then
  287.         Exit;
  288.  
  289.     Writeln('Stop listening to pipe');
  290.     pListenPipe^.fStopped := True;
  291.  
  292.     pListenPipe^.stop_pipe_func(pListenPipe^.hDevice);
  293.     WaitForSingleObject(pListenPipe^.hThread, INFINITE);
  294.     CloseHandle(pListenPipe^.hThread);
  295.     pListenPipe^.hThread := 0;
  296. end;
  297.  
  298.  
  299. procedure ListenToPipe(pListenPipe : PUSB_LISTEN_PIPE);
  300. var
  301.    threadId : DWORD;
  302.  
  303. begin
  304.     { start the running thread }
  305.     Writeln('Start listening to pipe');
  306.     pListenPipe^.hThread := CreateThread (nil, $1000, @PipeListenHandler, POINTER(pListenPipe), 0, threadId);
  307. end;
  308.  
  309.  
  310. function PipeListenHandler(pParam : POINTER) : DWORD; stdcall;
  311. var
  312.     pListenPipe : PUSB_LISTEN_PIPE;
  313.     pbuf : POINTER;
  314.     dwBytesTransfered : DWORD;
  315.  
  316. begin
  317.     pListenPipe := PUSB_LISTEN_PIPE(pParam);
  318.     GetMem(POINTER(pbuf), pListenPipe^.dwPacketSize);
  319.  
  320.     while True do
  321.     begin
  322.         dwBytesTransfered := pListenPipe^.read_pipe_func(pListenPipe^.hDevice, pbuf, pListenPipe^.dwPacketSize);
  323.         if pListenPipe^.fStopped then
  324.             BREAK;
  325.     if dwBytesTransfered = $ffffffff then
  326.     begin
  327.             writeln('Transfer failed');
  328.             BREAK;
  329.         end;
  330.         if @pListenPipe^.process_data_func <> POINTER(0) then
  331.             pListenPipe^.process_data_func(pbuf, dwBytesTransfered, pListenPipe^.pContext)
  332.         else
  333.             PrintHexBuffer(pbuf, dwBytesTransfered);
  334.     end;
  335.     FreeMem(pbuf);
  336.     PipeListenHandler := 0;
  337. end;
  338.  
  339.  
  340. function GetHexChar (line : string) : INTEGER;
  341. var
  342.     ch : INTEGER;
  343.     tmpStr : string;
  344.  
  345. begin
  346.     ch := Ord(line[1]);
  347.  
  348.     if (not IsHexDigit(line[1])) then
  349.     begin
  350.         GetHexChar := -1;
  351.         Exit;
  352.     end;
  353.  
  354.     if  ((ch >= Ord('0')) and (ch <= Ord('9'))) then
  355.        GetHexChar := StrToInt(line[1])
  356.     else
  357.         begin
  358.             tmpStr := UpperCase(line[1]);
  359.             GetHexChar := BYTE(tmpStr[1]) - BYTE('A') + 10;
  360.         end;
  361.  
  362. end;
  363.  
  364.  
  365. function GetHexBuffer(pBuffer : POINTER; dwBytes : DWORD) : DWORD;
  366. var
  367.     i , pos: DWORD;
  368.     pData : PBYTE;
  369.     res : BYTE;
  370.     ch : INTEGER;
  371.     line : string;
  372.     strLength : INTEGER;
  373.  
  374. begin
  375.     pData  := pBuffer;
  376.     i := 1;
  377.     pos := 0;
  378.     Readln(line);
  379.     strLength := Length(line);
  380.  
  381.     while pos < dwBytes do
  382.     begin
  383.         if i > strLength then
  384.         begin
  385.             Readln(line);
  386.             strLength := Length(line);
  387.             i := 1;
  388.         end;
  389.  
  390.         ch := GetHexChar(line[i]);
  391.         if ch<0 then
  392.         begin
  393.             i := i+1;
  394.             continue;
  395.         end;
  396.  
  397.         res := ch * 16;
  398.         i := i+1;
  399.  
  400.         if i > strLength then
  401.         begin
  402.             Readln(line);
  403.             strLength := Length(line);
  404.             i := 1;
  405.         end;
  406.  
  407.         ch := GetHexChar(line[i]);
  408.         if ch<0 then
  409.         begin
  410.             i := i+1;
  411.             continue;
  412.         end;
  413.  
  414.         res := res + ch;
  415.         PBYTE(DWORD(pData) +pos)^ := res;
  416.         i := i+1;
  417.         pos := pos+1;
  418.     end;
  419.  
  420.     // return the number of bytes that was read
  421.     GetHexBuffer := pos;
  422. end;
  423.  
  424.  
  425. function IsHexDigit(c : string) : BOOLEAN;
  426. var
  427.     cOrd : Longint;
  428. begin
  429.     cOrd := Ord(c[1]);
  430.     IsHexDigit := ((cOrd >= Ord('0')) and (cOrd <= Ord('9')))
  431.        or ((cOrd >= Ord('A')) and (cOrd <= Ord('F')))
  432.        or ((cOrd >= Ord('a')) and (cOrd <= Ord('f')));
  433. end;
  434.  
  435. end.
  436.  
  437.  
  438.